﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading.Tasks;
using alib.Debugging;

using alib.Hashing;
using alib.Enumerable;
using alib.Collections;
using alib.Array;

namespace alib.dg
{
	using String = System.String;
	using Enumerable = System.Linq.Enumerable;
	using Array = System.Array;

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	/// 
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public class ro_graph : dg
	{
		public ro_graph(Edge[] E, Vertex[] V)
			: base(E, V)
		{
		}
		public ro_graph()
			: this(default(Edge[]), default(Vertex[]))
		{
		}

		public ro_graph(ctor_args args)
			: this(args.E, args.V)
		{
		}

		public struct ctor_args
		{
			public Edge[] E;
			public Vertex[] V;
		};
	};


	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	///
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public class ro_data_graph<TEdge, TVertex> : ro_graph, IGraphData<TEdge, TVertex>
	{
		public ro_data_graph(IIndexedHash<TEdge> edict, IIndexedHash<TVertex> vdict, Edge[] E, Vertex[] V)
			: base(E, V)
		{
			this.edict = edict ?? new IndexedHash<TEdge>();
			this.vdict = vdict ?? new IndexedHash<TVertex>();
		}
		public ro_data_graph(Edge[] E, Vertex[] V)
			: this(default(IndexedHash<TEdge>), default(IndexedHash<TVertex>), E, V)
		{
		}
		public ro_data_graph()
			: this(default(Edge[]), default(Vertex[]))
		{
		}

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public readonly IIndexedHash<TEdge> edict;
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		public readonly IIndexedHash<TVertex> vdict;

		IIndexedHash<TEdge> IEindex<TEdge>.EDict { [DebuggerStepThrough] get { return edict; } }
		IIndexedHash<TVertex> IVindex<TVertex>.VDict { [DebuggerStepThrough] get { return vdict; } }

		public TEdge EdgeData(Eref e) { return edict[E[e].value]; }
		public TVertex VertexData(Vref v) { return vdict[V[v].value]; }

		public override String edge_string(Eref e)
		{
			return edict[E[e].value].ToString();
		}
		public override String vertex_string(Vref v)
		{
			return vdict[V[v].value].ToString();
		}
	};
}

namespace alib.dg
{
	using String = System.String;
	using debug;

	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	///
	///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	public class ro_string_graph : ro_data_graph<String, String>, IStringGraph
	{
		public ro_string_graph(IIndexedHash<String> edict, IIndexedHash<String> vdict, Edge[] E, Vertex[] V)
			: base(edict ?? new StringIndex(), vdict ?? new StringIndex(), E, V)
		{
		}
		public ro_string_graph(Edge[] E, Vertex[] V)
			: this(default(StringIndex), default(StringIndex), E, V)
		{
		}

#if DEBUG
		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		eent_dbg[] edbg;
		//[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
		[DebuggerDisplay("Count: {EdgeCount}", Name = "=== EDGES")]
		public eent_dbg[] z01_EDGES
		{
			[DebuggerStepThrough]
			get
			{
				int c = EdgeAlloc;
				if (edbg == null || edbg.Length != c)
				{
					edbg = new eent_dbg[c];
					for (Eref i = Eref.Zero; i < c; i++)
						edbg[i] = new eent_dbg(this, i);
				}
				return edbg;
			}
		}

		[DebuggerBrowsable(DebuggerBrowsableState.Never)]
		vent_dbg[] vdbg;
		//[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
		[DebuggerDisplay("Count: {VertexCount}", Name = "=== VERTICIES")]
		public vent_dbg[] z02_VERTICIES
		{
			[DebuggerStepThrough]
			get
			{
				int c = VertexAlloc;
				if (vdbg == null || vdbg.Length != c)
				{
					vdbg = new vent_dbg[c];
					for (Vref i = Vref.Zero; i < c; i++)
						vdbg[i] = new vent_dbg(this, i);
				}
				return vdbg;
			}
		}
#endif
	};
}